<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Extract horizontal and vertical lines by using morphological operations</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d9/df8/tutorial_root.html">OpenCV Tutorials</a></li><li class="navelem"><a class="el" href="../../d7/da8/tutorial_table_of_content_imgproc.html">Image Processing (imgproc module)</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Extract horizontal and vertical lines by using morphological operations </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><b>Prev Tutorial:</b> <a class="el" href="../../db/d06/tutorial_hitOrMiss.html">Hit-or-Miss</a></p>
<p><b>Next Tutorial:</b> <a class="el" href="../../d4/d1f/tutorial_pyramids.html">Image Pyramids</a></p>
<table class="doxtable">
<tr>
<th align="right"></th><th align="left"></th></tr>
<tr>
<td align="right">Original author </td><td align="left">Theodore Tsesmelis </td></tr>
<tr>
<td align="right">Compatibility </td><td align="left">OpenCV &gt;= 3.0 </td></tr>
</table>
<h2>Goal </h2>
<p>In this tutorial you will learn how to:</p>
<ul>
<li><p class="startli">Apply two very common morphology operators (i.e. Dilation and Erosion), with the creation of custom kernels, in order to extract straight lines on the horizontal and vertical axes. For this purpose, you will use the following OpenCV functions:</p><ul>
<li><b><a class="el" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb" title="Erodes an image by using a specific structuring element. ">erode()</a></b></li>
<li><b><a class="el" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c" title="Dilates an image by using a specific structuring element. ">dilate()</a></b></li>
<li><b><a class="el" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc" title="Returns a structuring element of the specified size and shape for morphological operations. ">getStructuringElement()</a></b></li>
</ul>
<p class="startli">in an example where your goal will be to extract the music notes from a music sheet.</p>
</li>
</ul>
<h2>Theory </h2>
<h3>Morphology Operations</h3>
<p>Morphology is a set of image processing operations that process images based on predefined <em>structuring elements</em> known also as kernels. The value of each pixel in the output image is based on a comparison of the corresponding pixel in the input image with its neighbors. By choosing the size and shape of the kernel, you can construct a morphological operation that is sensitive to specific shapes regarding the input image.</p>
<p>Two of the most basic morphological operations are dilation and erosion. Dilation adds pixels to the boundaries of the object in an image, while erosion does exactly the opposite. The amount of pixels added or removed, respectively depends on the size and shape of the structuring element used to process the image. In general the rules followed from these two operations have as follows:</p>
<ul>
<li><p class="startli"><b>Dilation</b>: The value of the output pixel is the <b><em>maximum</em></b> value of all the pixels that fall within the structuring element's size and shape. For example in a binary image, if any of the pixels of the input image falling within the range of the kernel is set to the value 1, the corresponding pixel of the output image will be set to 1 as well. The latter applies to any type of image (e.g. grayscale, bgr, etc).</p>
<div class="image">
<img src="../../morph21.gif" alt="morph21.gif"/>
<div class="caption">
Dilation on a Binary Image</div></div>
 <div class="image">
<img src="../../morph6.gif" alt="morph6.gif"/>
<div class="caption">
Dilation on a Grayscale Image</div></div>
</li>
<li><p class="startli"><b>Erosion</b>: The vice versa applies for the erosion operation. The value of the output pixel is the <b><em>minimum</em></b> value of all the pixels that fall within the structuring element's size and shape. Look the at the example figures below:</p>
<div class="image">
<img src="../../morph211.png" alt="morph211.png"/>
<div class="caption">
Erosion on a Binary Image</div></div>
 <div class="image">
<img src="../../morph61.png" alt="morph61.png"/>
<div class="caption">
Erosion on a Grayscale Image</div></div>
 <h3>Structuring Elements</h3>
</li>
</ul>
<p>As it can be seen above and in general in any morphological operation the structuring element used to probe the input image, is the most important part.</p>
<p>A structuring element is a matrix consisting of only 0's and 1's that can have any arbitrary shape and size. Typically are much smaller than the image being processed, while the pixels with values of 1 define the neighborhood. The center pixel of the structuring element, called the origin, identifies the pixel of interest &ndash; the pixel being processed.</p>
<p>For example, the following illustrates a diamond-shaped structuring element of 7x7 size.</p>
<div class="image">
<img src="../../morph12.gif" alt="morph12.gif"/>
<div class="caption">
A Diamond-Shaped Structuring Element and its Origin</div></div>
<p> A structuring element can have many common shapes, such as lines, diamonds, disks, periodic lines, and circles and sizes. You typically choose a structuring element the same size and shape as the objects you want to process/extract in the input image. For example, to find lines in an image, create a linear structuring element as you will see later.</p>
<h2>Code </h2>
<p>This tutorial code's is shown lines below.</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'><p> You can also download it from <a href="https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.cpp">here</a>. </p><div class="fragment"><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d0/d9c/core_2include_2opencv2_2core_8hpp.html">opencv2/core.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">opencv2/imgproc.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d4/dd5/highgui_8hpp.html">opencv2/highgui.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"></div><div class="line"><span class="keywordtype">void</span> show_wait_destroy(<span class="keyword">const</span> <span class="keywordtype">char</span>* winname, <a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> img);</div><div class="line"></div><div class="line"><span class="keyword">using namespace </span>std;</div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>** argv)</div><div class="line">{</div><div class="line">    <a class="code" href="../../d0/d2e/classcv_1_1CommandLineParser.html">CommandLineParser</a> parser(argc, argv, <span class="stringliteral">&quot;{@input | notes.png | input image}&quot;</span>);</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> src = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( <a class="code" href="../../d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13">samples::findFile</a>( parser.get&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt;(<span class="stringliteral">&quot;@input&quot;</span>) ), <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80af660544735200cbe942eea09232eb822">IMREAD_COLOR</a>);</div><div class="line">    <span class="keywordflow">if</span> (src.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abbec3525a852e77998aba034813fded4">empty</a>())</div><div class="line">    {</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;Could not open or find the image!\n&quot;</span> &lt;&lt; endl;</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;Usage: &quot;</span> &lt;&lt; argv[0] &lt;&lt; <span class="stringliteral">&quot; &lt;Input image&gt;&quot;</span> &lt;&lt; endl;</div><div class="line">        <span class="keywordflow">return</span> -1;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Show source image</span></div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>(<span class="stringliteral">&quot;src&quot;</span>, src);</div><div class="line"></div><div class="line">    <span class="comment">// Transform source image to gray if it is not already</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> gray;</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (src.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa11336b9ac538e0475d840657ce164be">channels</a>() == 3)</div><div class="line">    {</div><div class="line">        <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cvtColor</a>(src, gray, <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0a353a4b8db9040165db4dacb5bcefb6ea">COLOR_BGR2GRAY</a>);</div><div class="line">    }</div><div class="line">    <span class="keywordflow">else</span></div><div class="line">    {</div><div class="line">        gray = src;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Show gray image</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;gray&quot;</span>, gray);</div><div class="line"></div><div class="line">    <span class="comment">// Apply adaptiveThreshold at the bitwise_not of gray, notice the ~ symbol</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> bw;</div><div class="line">    <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3">adaptiveThreshold</a>(~gray, bw, 255, <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa42a3e6ef26247da787bf34030ed772cad0c5199ae8637a6b195062fea4789fa9">ADAPTIVE_THRESH_MEAN_C</a>, <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa9e58d2860d4afa658ef70a9b1115576a147222a96556ebc1d948b372bcd7ac59">THRESH_BINARY</a>, 15, -2);</div><div class="line"></div><div class="line">    <span class="comment">// Show binary image</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;binary&quot;</span>, bw);</div><div class="line"></div><div class="line">    <span class="comment">// Create the images that will use to extract the horizontal and vertical lines</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> horizontal = bw.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adff2ea98da45eae0833e73582dd4a660">clone</a>();</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> vertical = bw.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adff2ea98da45eae0833e73582dd4a660">clone</a>();</div><div class="line"></div><div class="line">    <span class="comment">// Specify size on horizontal axis</span></div><div class="line">    <span class="keywordtype">int</span> horizontal_size = horizontal.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa3e5a47585c9ef6a0842556739155e3e">cols</a> / 30;</div><div class="line"></div><div class="line">    <span class="comment">// Create structure element for extracting horizontal lines through morphology operations</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> horizontalStructure = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">getStructuringElement</a>(<a class="code" href="../../d4/d86/group__imgproc__filter.html#ggac2db39b56866583a95a5680313c314ada260c4cbde19a749726763c01a074c60f">MORPH_RECT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(horizontal_size, 1));</div><div class="line"></div><div class="line">    <span class="comment">// Apply morphology operations</span></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb">erode</a>(horizontal, horizontal, horizontalStructure, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(-1, -1));</div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">dilate</a>(horizontal, horizontal, horizontalStructure, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(-1, -1));</div><div class="line"></div><div class="line">    <span class="comment">// Show extracted horizontal lines</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;horizontal&quot;</span>, horizontal);</div><div class="line"></div><div class="line">    <span class="comment">// Specify size on vertical axis</span></div><div class="line">    <span class="keywordtype">int</span> vertical_size = vertical.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abed816466c45234254d25bc59c31245e">rows</a> / 30;</div><div class="line"></div><div class="line">    <span class="comment">// Create structure element for extracting vertical lines through morphology operations</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> verticalStructure = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">getStructuringElement</a>(<a class="code" href="../../d4/d86/group__imgproc__filter.html#ggac2db39b56866583a95a5680313c314ada260c4cbde19a749726763c01a074c60f">MORPH_RECT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(1, vertical_size));</div><div class="line"></div><div class="line">    <span class="comment">// Apply morphology operations</span></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb">erode</a>(vertical, vertical, verticalStructure, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(-1, -1));</div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">dilate</a>(vertical, vertical, verticalStructure, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(-1, -1));</div><div class="line"></div><div class="line">    <span class="comment">// Show extracted vertical lines</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;vertical&quot;</span>, vertical);</div><div class="line"></div><div class="line">    <span class="comment">// Inverse vertical image</span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga0002cf8b418479f4cb49a75442baee2f">bitwise_not</a>(vertical, vertical);</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;vertical_bit&quot;</span>, vertical);</div><div class="line"></div><div class="line">    <span class="comment">// Extract edges and smooth image according to the logic</span></div><div class="line">    <span class="comment">// 1. extract edges</span></div><div class="line">    <span class="comment">// 2. dilate(edges)</span></div><div class="line">    <span class="comment">// 3. src.copyTo(smooth)</span></div><div class="line">    <span class="comment">// 4. blur smooth img</span></div><div class="line">    <span class="comment">// 5. smooth.copyTo(src, edges)</span></div><div class="line"></div><div class="line">    <span class="comment">// Step 1</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> edges;</div><div class="line">    <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3">adaptiveThreshold</a>(vertical, edges, 255, <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa42a3e6ef26247da787bf34030ed772cad0c5199ae8637a6b195062fea4789fa9">ADAPTIVE_THRESH_MEAN_C</a>, <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa9e58d2860d4afa658ef70a9b1115576a147222a96556ebc1d948b372bcd7ac59">THRESH_BINARY</a>, 3, -2);</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;edges&quot;</span>, edges);</div><div class="line"></div><div class="line">    <span class="comment">// Step 2</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> kernel = Mat::ones(2, 2, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga81df635441b21f532fdace401e04f588">CV_8UC1</a>);</div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">dilate</a>(edges, edges, kernel);</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;dilate&quot;</span>, edges);</div><div class="line"></div><div class="line">    <span class="comment">// Step 3</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> smooth;</div><div class="line">    vertical.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>(smooth);</div><div class="line"></div><div class="line">    <span class="comment">// Step 4</span></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga8c45db9afe636703801b0b2e440fce37">blur</a>(smooth, smooth, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(2, 2));</div><div class="line"></div><div class="line">    <span class="comment">// Step 5</span></div><div class="line">    smooth.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>(vertical, edges);</div><div class="line"></div><div class="line">    <span class="comment">// Show final result</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;smooth - final&quot;</span>, vertical);</div><div class="line"></div><div class="line">    <span class="keywordflow">return</span> 0;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> show_wait_destroy(<span class="keyword">const</span> <span class="keywordtype">char</span>* winname, <a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> img) {</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>(winname, img);</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga8d86b207f7211250dbe6e28f76307ffb">moveWindow</a>(winname, 500, 0);</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">waitKey</a>(0);</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga851ccdd6961022d1d5b4c4f255dbab34">destroyWindow</a>(winname);</div><div class="line">}</div></div><!-- fragment -->  </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'><p> You can also download it from <a href="https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgProc/morph_lines_detection/Morphology_3.java">here</a>. </p><div class="fragment"><div class="line"></div><div class="line"><span class="keyword">import</span> org.opencv.core.*;</div><div class="line"><span class="keyword">import</span> org.opencv.highgui.HighGui;</div><div class="line"><span class="keyword">import</span> org.opencv.imgcodecs.Imgcodecs;</div><div class="line"><span class="keyword">import</span> org.opencv.imgproc.Imgproc;</div><div class="line"></div><div class="line"><span class="keyword">class </span>Morphology_3Run {</div><div class="line"></div><div class="line">    <span class="keyword">public</span> <span class="keywordtype">void</span> run(<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>[] args) {</div><div class="line"></div><div class="line">        <span class="comment">// Check number of arguments</span></div><div class="line">        <span class="keywordflow">if</span> (args.length == 0){</div><div class="line">            System.out.println(<span class="stringliteral">&quot;Not enough parameters!&quot;</span>);</div><div class="line">            System.out.println(<span class="stringliteral">&quot;Program Arguments: [image_path]&quot;</span>);</div><div class="line">            System.exit(-1);</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">// Load the image</span></div><div class="line">        Mat src = Imgcodecs.imread(args[0]);</div><div class="line"></div><div class="line">        <span class="comment">// Check if image is loaded fine</span></div><div class="line">        <span class="keywordflow">if</span>( src.empty() ) {</div><div class="line">            System.out.println(<span class="stringliteral">&quot;Error opening image: &quot;</span> + args[0]);</div><div class="line">            System.exit(-1);</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">// Show source image</span></div><div class="line">        HighGui.imshow(<span class="stringliteral">&quot;src&quot;</span>, src);</div><div class="line"></div><div class="line">        <span class="comment">// Transform source image to gray if it is not already</span></div><div class="line">        Mat gray = <span class="keyword">new</span> Mat();</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (src.channels() == 3)</div><div class="line">        {</div><div class="line">            Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">        {</div><div class="line">            gray = src;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">// Show gray image</span></div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;gray&quot;</span> , gray);</div><div class="line"></div><div class="line">        <span class="comment">// Apply adaptiveThreshold at the bitwise_not of gray</span></div><div class="line">        Mat bw = <span class="keyword">new</span> Mat();</div><div class="line">        Core.bitwise_not(gray, gray);</div><div class="line">        Imgproc.adaptiveThreshold(gray, bw, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 15, -2);</div><div class="line"></div><div class="line">        <span class="comment">// Show binary image</span></div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;binary&quot;</span> , bw);</div><div class="line"></div><div class="line">        <span class="comment">// Create the images that will use to extract the horizontal and vertical lines</span></div><div class="line">        Mat horizontal = bw.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adff2ea98da45eae0833e73582dd4a660">clone</a>();</div><div class="line">        Mat vertical = bw.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adff2ea98da45eae0833e73582dd4a660">clone</a>();</div><div class="line"></div><div class="line">        <span class="comment">// Specify size on horizontal axis</span></div><div class="line">        <span class="keywordtype">int</span> horizontal_size = horizontal.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa3e5a47585c9ef6a0842556739155e3e">cols</a>() / 30;</div><div class="line"></div><div class="line">        <span class="comment">// Create structure element for extracting horizontal lines through morphology operations</span></div><div class="line">        Mat horizontalStructure = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(horizontal_size,1));</div><div class="line"></div><div class="line">        <span class="comment">// Apply morphology operations</span></div><div class="line">        Imgproc.erode(horizontal, horizontal, horizontalStructure);</div><div class="line">        Imgproc.dilate(horizontal, horizontal, horizontalStructure);</div><div class="line"></div><div class="line">        <span class="comment">// Show extracted horizontal lines</span></div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;horizontal&quot;</span> , horizontal);</div><div class="line"></div><div class="line">        <span class="comment">// Specify size on vertical axis</span></div><div class="line">        <span class="keywordtype">int</span> vertical_size = vertical.rows() / 30;</div><div class="line"></div><div class="line">        <span class="comment">// Create structure element for extracting vertical lines through morphology operations</span></div><div class="line">        Mat verticalStructure = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( 1,vertical_size));</div><div class="line"></div><div class="line">        <span class="comment">// Apply morphology operations</span></div><div class="line">        Imgproc.erode(vertical, vertical, verticalStructure);</div><div class="line">        Imgproc.dilate(vertical, vertical, verticalStructure);</div><div class="line"></div><div class="line">        <span class="comment">// Show extracted vertical lines</span></div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;vertical&quot;</span>, vertical);</div><div class="line"></div><div class="line">        <span class="comment">// Inverse vertical image</span></div><div class="line">        Core.bitwise_not(vertical, vertical);</div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;vertical_bit&quot;</span> , vertical);</div><div class="line"></div><div class="line">        <span class="comment">// Extract edges and smooth image according to the logic</span></div><div class="line">        <span class="comment">// 1. extract edges</span></div><div class="line">        <span class="comment">// 2. dilate(edges)</span></div><div class="line">        <span class="comment">// 3. src.copyTo(smooth)</span></div><div class="line">        <span class="comment">// 4. blur smooth img</span></div><div class="line">        <span class="comment">// 5. smooth.copyTo(src, edges)</span></div><div class="line"></div><div class="line">        <span class="comment">// Step 1</span></div><div class="line">        Mat edges = <span class="keyword">new</span> Mat();</div><div class="line">        Imgproc.adaptiveThreshold(vertical, edges, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 3, -2);</div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;edges&quot;</span>, edges);</div><div class="line"></div><div class="line">        <span class="comment">// Step 2</span></div><div class="line">        Mat kernel = Mat.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a69ae0402d116fc9c71908d8508dc2f09">ones</a>(2, 2, CvType.CV_8UC1);</div><div class="line">        Imgproc.dilate(edges, edges, kernel);</div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;dilate&quot;</span>, edges);</div><div class="line"></div><div class="line">        <span class="comment">// Step 3</span></div><div class="line">        Mat smooth = <span class="keyword">new</span> Mat();</div><div class="line">        vertical.copyTo(smooth);</div><div class="line"></div><div class="line">        <span class="comment">// Step 4</span></div><div class="line">        Imgproc.blur(smooth, smooth, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(2, 2));</div><div class="line"></div><div class="line">        <span class="comment">// Step 5</span></div><div class="line">        smooth.copyTo(vertical, edges);</div><div class="line"></div><div class="line">        <span class="comment">// Show final result</span></div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;smooth - final&quot;</span>, vertical);</div><div class="line"></div><div class="line">        System.exit(0);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keyword">private</span> <span class="keywordtype">void</span> showWaitDestroy(<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> winname, Mat img) {</div><div class="line">        HighGui.imshow(winname, img);</div><div class="line">        HighGui.moveWindow(winname, 500, 0);</div><div class="line">        HighGui.waitKey(0);</div><div class="line">        HighGui.destroyWindow(winname);</div><div class="line">    }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="keyword">class </span>Morphology_3 {</div><div class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keywordtype">void</span> main(<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>[] args) {</div><div class="line">        <span class="comment">// Load the native library.</span></div><div class="line">        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);</div><div class="line">        <span class="keyword">new</span> Morphology_3Run().run(args);</div><div class="line">    }</div><div class="line">}</div></div><!-- fragment -->  </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'><p> You can also download it from <a href="https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/imgProc/morph_lines_detection/morph_lines_detection.py">here</a>. </p><div class="fragment"><div class="line"><span class="stringliteral">&quot;&quot;&quot;</span></div><div class="line"><span class="stringliteral">@file morph_lines_detection.py</span></div><div class="line"><span class="stringliteral">@brief Use morphology transformations for extracting horizontal and vertical lines sample code</span></div><div class="line"><span class="stringliteral">&quot;&quot;&quot;</span></div><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"><span class="keyword">import</span> sys</div><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">def </span>show_wait_destroy(winname, img):</div><div class="line">    <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(winname, img)</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga8d86b207f7211250dbe6e28f76307ffb">cv.moveWindow</a>(winname, 500, 0)</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv.waitKey</a>(0)</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga851ccdd6961022d1d5b4c4f255dbab34">cv.destroyWindow</a>(winname)</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">def </span>main(argv):</div><div class="line">    <span class="comment"># [load_image]</span></div><div class="line">    <span class="comment"># Check number of arguments</span></div><div class="line">    <span class="keywordflow">if</span> len(argv) &lt; 1:</div><div class="line">        <span class="keywordflow">print</span> (<span class="stringliteral">&#39;Not enough parameters&#39;</span>)</div><div class="line">        <span class="keywordflow">print</span> (<span class="stringliteral">&#39;Usage:\nmorph_lines_detection.py &lt; path_to_image &gt;&#39;</span>)</div><div class="line">        <span class="keywordflow">return</span> -1</div><div class="line"></div><div class="line">    <span class="comment"># Load the image</span></div><div class="line">    src = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(argv[0], cv.IMREAD_COLOR)</div><div class="line"></div><div class="line">    <span class="comment"># Check if image is loaded fine</span></div><div class="line">    <span class="keywordflow">if</span> src <span class="keywordflow">is</span> <span class="keywordtype">None</span>:</div><div class="line">        <span class="keywordflow">print</span> (<span class="stringliteral">&#39;Error opening image: &#39;</span> + argv[0])</div><div class="line">        <span class="keywordflow">return</span> -1</div><div class="line"></div><div class="line">    <span class="comment"># Show source image</span></div><div class="line">    <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(<span class="stringliteral">&quot;src&quot;</span>, src)</div><div class="line">    <span class="comment"># [load_image]</span></div><div class="line"></div><div class="line">    <span class="comment"># [gray]</span></div><div class="line">    <span class="comment"># Transform source image to gray if it is not already</span></div><div class="line">    <span class="keywordflow">if</span> len(src.shape) != 2:</div><div class="line">        gray = <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cv.cvtColor</a>(src, cv.COLOR_BGR2GRAY)</div><div class="line">    <span class="keywordflow">else</span>:</div><div class="line">        gray = src</div><div class="line"></div><div class="line">    <span class="comment"># Show gray image</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;gray&quot;</span>, gray)</div><div class="line">    <span class="comment"># [gray]</span></div><div class="line"></div><div class="line">    <span class="comment"># [bin]</span></div><div class="line">    <span class="comment"># Apply adaptiveThreshold at the bitwise_not of gray, notice the ~ symbol</span></div><div class="line">    gray = <a class="code" href="../../d2/de8/group__core__array.html#ga0002cf8b418479f4cb49a75442baee2f">cv.bitwise_not</a>(gray)</div><div class="line">    bw = <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3">cv.adaptiveThreshold</a>(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, \</div><div class="line">                                cv.THRESH_BINARY, 15, -2)</div><div class="line">    <span class="comment"># Show binary image</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;binary&quot;</span>, bw)</div><div class="line">    <span class="comment"># [bin]</span></div><div class="line"></div><div class="line">    <span class="comment"># [init]</span></div><div class="line">    <span class="comment"># Create the images that will use to extract the horizontal and vertical lines</span></div><div class="line">    horizontal = np.copy(bw)</div><div class="line">    vertical = np.copy(bw)</div><div class="line">    <span class="comment"># [init]</span></div><div class="line"></div><div class="line">    <span class="comment"># [horiz]</span></div><div class="line">    <span class="comment"># Specify size on horizontal axis</span></div><div class="line">    cols = horizontal.shape[1]</div><div class="line">    horizontal_size = cols // 30</div><div class="line"></div><div class="line">    <span class="comment"># Create structure element for extracting horizontal lines through morphology operations</span></div><div class="line">    horizontalStructure = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">cv.getStructuringElement</a>(cv.MORPH_RECT, (horizontal_size, 1))</div><div class="line"></div><div class="line">    <span class="comment"># Apply morphology operations</span></div><div class="line">    horizontal = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb">cv.erode</a>(horizontal, horizontalStructure)</div><div class="line">    horizontal = <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">cv.dilate</a>(horizontal, horizontalStructure)</div><div class="line"></div><div class="line">    <span class="comment"># Show extracted horizontal lines</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;horizontal&quot;</span>, horizontal)</div><div class="line">    <span class="comment"># [horiz]</span></div><div class="line"></div><div class="line">    <span class="comment"># [vert]</span></div><div class="line">    <span class="comment"># Specify size on vertical axis</span></div><div class="line">    rows = vertical.shape[0]</div><div class="line">    verticalsize = rows // 30</div><div class="line"></div><div class="line">    <span class="comment"># Create structure element for extracting vertical lines through morphology operations</span></div><div class="line">    verticalStructure = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">cv.getStructuringElement</a>(cv.MORPH_RECT, (1, verticalsize))</div><div class="line"></div><div class="line">    <span class="comment"># Apply morphology operations</span></div><div class="line">    vertical = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb">cv.erode</a>(vertical, verticalStructure)</div><div class="line">    vertical = <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">cv.dilate</a>(vertical, verticalStructure)</div><div class="line"></div><div class="line">    <span class="comment"># Show extracted vertical lines</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;vertical&quot;</span>, vertical)</div><div class="line">    <span class="comment"># [vert]</span></div><div class="line"></div><div class="line">    <span class="comment"># [smooth]</span></div><div class="line">    <span class="comment"># Inverse vertical image</span></div><div class="line">    vertical = <a class="code" href="../../d2/de8/group__core__array.html#ga0002cf8b418479f4cb49a75442baee2f">cv.bitwise_not</a>(vertical)</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;vertical_bit&quot;</span>, vertical)</div><div class="line"></div><div class="line">    <span class="stringliteral">&#39;&#39;&#39;</span></div><div class="line"><span class="stringliteral">    Extract edges and smooth image according to the logic</span></div><div class="line"><span class="stringliteral">    1. extract edges</span></div><div class="line"><span class="stringliteral">    2. dilate(edges)</span></div><div class="line"><span class="stringliteral">    3. src.copyTo(smooth)</span></div><div class="line"><span class="stringliteral">    4. blur smooth img</span></div><div class="line"><span class="stringliteral">    5. smooth.copyTo(src, edges)</span></div><div class="line"><span class="stringliteral">    &#39;&#39;&#39;</span></div><div class="line"></div><div class="line">    <span class="comment"># Step 1</span></div><div class="line">    edges = <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3">cv.adaptiveThreshold</a>(vertical, 255, cv.ADAPTIVE_THRESH_MEAN_C, \</div><div class="line">                                cv.THRESH_BINARY, 3, -2)</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;edges&quot;</span>, edges)</div><div class="line"></div><div class="line">    <span class="comment"># Step 2</span></div><div class="line">    kernel = np.ones((2, 2), np.uint8)</div><div class="line">    edges = <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">cv.dilate</a>(edges, kernel)</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;dilate&quot;</span>, edges)</div><div class="line"></div><div class="line">    <span class="comment"># Step 3</span></div><div class="line">    smooth = np.copy(vertical)</div><div class="line"></div><div class="line">    <span class="comment"># Step 4</span></div><div class="line">    smooth = <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga8c45db9afe636703801b0b2e440fce37">cv.blur</a>(smooth, (2, 2))</div><div class="line"></div><div class="line">    <span class="comment"># Step 5</span></div><div class="line">    (rows, cols) = np.where(edges != 0)</div><div class="line">    vertical[rows, cols] = smooth[rows, cols]</div><div class="line"></div><div class="line">    <span class="comment"># Show final result</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;smooth - final&quot;</span>, vertical)</div><div class="line">    <span class="comment"># [smooth]</span></div><div class="line"></div><div class="line">    <span class="keywordflow">return</span> 0</div><div class="line"></div><div class="line"><span class="keywordflow">if</span> __name__ == <span class="stringliteral">&quot;__main__&quot;</span>:</div><div class="line">    main(sys.argv[1:])</div></div><!-- fragment -->  </div> <h2>Explanation / Result </h2>
<p>Get image from <a href="https://raw.githubusercontent.com/opencv/opencv/master/doc/tutorials/imgproc/morph_lines_detection/images/src.png">here</a> .</p>
<h4>Load Image</h4>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    CommandLineParser parser(argc, argv, <span class="stringliteral">&quot;{@input | notes.png | input image}&quot;</span>);</div><div class="line">    Mat src = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( <a class="code" href="../../d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13">samples::findFile</a>( parser.get&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt;(<span class="stringliteral">&quot;@input&quot;</span>) ), <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80af660544735200cbe942eea09232eb822">IMREAD_COLOR</a>);</div><div class="line">    <span class="keywordflow">if</span> (src.empty())</div><div class="line">    {</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;Could not open or find the image!\n&quot;</span> &lt;&lt; endl;</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;Usage: &quot;</span> &lt;&lt; argv[0] &lt;&lt; <span class="stringliteral">&quot; &lt;Input image&gt;&quot;</span> &lt;&lt; endl;</div><div class="line">        <span class="keywordflow">return</span> -1;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Show source image</span></div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>(<span class="stringliteral">&quot;src&quot;</span>, src);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        <span class="comment">// Check number of arguments</span></div><div class="line">        <span class="keywordflow">if</span> (args.length == 0){</div><div class="line">            System.out.println(<span class="stringliteral">&quot;Not enough parameters!&quot;</span>);</div><div class="line">            System.out.println(<span class="stringliteral">&quot;Program Arguments: [image_path]&quot;</span>);</div><div class="line">            System.exit(-1);</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">// Load the image</span></div><div class="line">        Mat src = Imgcodecs.imread(args[0]);</div><div class="line"></div><div class="line">        <span class="comment">// Check if image is loaded fine</span></div><div class="line">        <span class="keywordflow">if</span>( src.empty() ) {</div><div class="line">            System.out.println(<span class="stringliteral">&quot;Error opening image: &quot;</span> + args[0]);</div><div class="line">            System.exit(-1);</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">// Show source image</span></div><div class="line">        HighGui.imshow(<span class="stringliteral">&quot;src&quot;</span>, src);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment"># Check number of arguments</span></div><div class="line">    <span class="keywordflow">if</span> len(argv) &lt; 1:</div><div class="line">        <span class="keywordflow">print</span> (<span class="stringliteral">&#39;Not enough parameters&#39;</span>)</div><div class="line">        <span class="keywordflow">print</span> (<span class="stringliteral">&#39;Usage:\nmorph_lines_detection.py &lt; path_to_image &gt;&#39;</span>)</div><div class="line">        <span class="keywordflow">return</span> -1</div><div class="line"></div><div class="line">    <span class="comment"># Load the image</span></div><div class="line">    src = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(argv[0], cv.IMREAD_COLOR)</div><div class="line"></div><div class="line">    <span class="comment"># Check if image is loaded fine</span></div><div class="line">    <span class="keywordflow">if</span> src <span class="keywordflow">is</span> <span class="keywordtype">None</span>:</div><div class="line">        <span class="keywordflow">print</span> (<span class="stringliteral">&#39;Error opening image: &#39;</span> + argv[0])</div><div class="line">        <span class="keywordflow">return</span> -1</div><div class="line"></div><div class="line">    <span class="comment"># Show source image</span></div><div class="line">    <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(<span class="stringliteral">&quot;src&quot;</span>, src)</div></div><!-- fragment --> </div> <div class="image">
<img src="../../src.png" alt="src.png"/>
</div>
<h4>Grayscale</h4>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment">// Transform source image to gray if it is not already</span></div><div class="line">    Mat gray;</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (src.channels() == 3)</div><div class="line">    {</div><div class="line">        <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cvtColor</a>(src, gray, <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0a353a4b8db9040165db4dacb5bcefb6ea">COLOR_BGR2GRAY</a>);</div><div class="line">    }</div><div class="line">    <span class="keywordflow">else</span></div><div class="line">    {</div><div class="line">        gray = src;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="comment">// Show gray image</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;gray&quot;</span>, gray);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        <span class="comment">// Transform source image to gray if it is not already</span></div><div class="line">        Mat gray = <span class="keyword">new</span> Mat();</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (src.channels() == 3)</div><div class="line">        {</div><div class="line">            Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);</div><div class="line">        }</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">        {</div><div class="line">            gray = src;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">// Show gray image</span></div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;gray&quot;</span> , gray);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment"># Transform source image to gray if it is not already</span></div><div class="line">    <span class="keywordflow">if</span> len(src.shape) != 2:</div><div class="line">        gray = <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cv.cvtColor</a>(src, cv.COLOR_BGR2GRAY)</div><div class="line">    <span class="keywordflow">else</span>:</div><div class="line">        gray = src</div><div class="line"></div><div class="line">    <span class="comment"># Show gray image</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;gray&quot;</span>, gray)</div></div><!-- fragment --> </div> <div class="image">
<img src="../../gray.png" alt="gray.png"/>
</div>
<h4>Grayscale to Binary image</h4>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment">// Apply adaptiveThreshold at the bitwise_not of gray, notice the ~ symbol</span></div><div class="line">    Mat bw;</div><div class="line">    <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3">adaptiveThreshold</a>(~gray, bw, 255, <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa42a3e6ef26247da787bf34030ed772cad0c5199ae8637a6b195062fea4789fa9">ADAPTIVE_THRESH_MEAN_C</a>, <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa9e58d2860d4afa658ef70a9b1115576a147222a96556ebc1d948b372bcd7ac59">THRESH_BINARY</a>, 15, -2);</div><div class="line"></div><div class="line">    <span class="comment">// Show binary image</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;binary&quot;</span>, bw);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        <span class="comment">// Apply adaptiveThreshold at the bitwise_not of gray</span></div><div class="line">        Mat bw = <span class="keyword">new</span> Mat();</div><div class="line">        Core.bitwise_not(gray, gray);</div><div class="line">        Imgproc.adaptiveThreshold(gray, bw, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 15, -2);</div><div class="line"></div><div class="line">        <span class="comment">// Show binary image</span></div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;binary&quot;</span> , bw);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment"># Apply adaptiveThreshold at the bitwise_not of gray, notice the ~ symbol</span></div><div class="line">    gray = <a class="code" href="../../d2/de8/group__core__array.html#ga0002cf8b418479f4cb49a75442baee2f">cv.bitwise_not</a>(gray)</div><div class="line">    bw = <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3">cv.adaptiveThreshold</a>(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, \</div><div class="line">                                cv.THRESH_BINARY, 15, -2)</div><div class="line">    <span class="comment"># Show binary image</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;binary&quot;</span>, bw)</div></div><!-- fragment --> </div> <div class="image">
<img src="../../binary.png" alt="binary.png"/>
</div>
<h4>Output images</h4>
<p>Now we are ready to apply morphological operations in order to extract the horizontal and vertical lines and as a consequence to separate the the music notes from the music sheet, but first let's initialize the output images that we will use for that reason:</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment">// Create the images that will use to extract the horizontal and vertical lines</span></div><div class="line">    Mat horizontal = bw.clone();</div><div class="line">    Mat vertical = bw.clone();</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        <span class="comment">// Create the images that will use to extract the horizontal and vertical lines</span></div><div class="line">        Mat horizontal = bw.clone();</div><div class="line">        Mat vertical = bw.clone();</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment"># Create the images that will use to extract the horizontal and vertical lines</span></div><div class="line">    horizontal = np.copy(bw)</div><div class="line">    vertical = np.copy(bw)</div></div><!-- fragment --> </div> <h4>Structure elements</h4>
<p>As we specified in the theory in order to extract the object that we desire, we need to create the corresponding structure element. Since we want to extract the horizontal lines, a corresponding structure element for that purpose will have the following shape: </p><div class="image">
<img src="../../linear_horiz.png" alt="linear_horiz.png"/>
</div>
<p> and in the source code this is represented by the following code snippet:</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment">// Specify size on horizontal axis</span></div><div class="line">    <span class="keywordtype">int</span> horizontal_size = horizontal.cols / 30;</div><div class="line"></div><div class="line">    <span class="comment">// Create structure element for extracting horizontal lines through morphology operations</span></div><div class="line">    Mat horizontalStructure = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">getStructuringElement</a>(<a class="code" href="../../d4/d86/group__imgproc__filter.html#ggac2db39b56866583a95a5680313c314ada260c4cbde19a749726763c01a074c60f">MORPH_RECT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(horizontal_size, 1));</div><div class="line"></div><div class="line">    <span class="comment">// Apply morphology operations</span></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb">erode</a>(horizontal, horizontal, horizontalStructure, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(-1, -1));</div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">dilate</a>(horizontal, horizontal, horizontalStructure, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(-1, -1));</div><div class="line"></div><div class="line">    <span class="comment">// Show extracted horizontal lines</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;horizontal&quot;</span>, horizontal);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        <span class="comment">// Specify size on horizontal axis</span></div><div class="line">        <span class="keywordtype">int</span> horizontal_size = horizontal.cols() / 30;</div><div class="line"></div><div class="line">        <span class="comment">// Create structure element for extracting horizontal lines through morphology operations</span></div><div class="line">        Mat horizontalStructure = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(horizontal_size,1));</div><div class="line"></div><div class="line">        <span class="comment">// Apply morphology operations</span></div><div class="line">        Imgproc.erode(horizontal, horizontal, horizontalStructure);</div><div class="line">        Imgproc.dilate(horizontal, horizontal, horizontalStructure);</div><div class="line"></div><div class="line">        <span class="comment">// Show extracted horizontal lines</span></div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;horizontal&quot;</span> , horizontal);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment"># Specify size on horizontal axis</span></div><div class="line">    cols = horizontal.shape[1]</div><div class="line">    horizontal_size = cols // 30</div><div class="line"></div><div class="line">    <span class="comment"># Create structure element for extracting horizontal lines through morphology operations</span></div><div class="line">    horizontalStructure = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">cv.getStructuringElement</a>(cv.MORPH_RECT, (horizontal_size, 1))</div><div class="line"></div><div class="line">    <span class="comment"># Apply morphology operations</span></div><div class="line">    horizontal = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb">cv.erode</a>(horizontal, horizontalStructure)</div><div class="line">    horizontal = <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">cv.dilate</a>(horizontal, horizontalStructure)</div><div class="line"></div><div class="line">    <span class="comment"># Show extracted horizontal lines</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;horizontal&quot;</span>, horizontal)</div></div><!-- fragment --> </div> <div class="image">
<img src="../../horiz.png" alt="horiz.png"/>
</div>
<p>The same applies for the vertical lines, with the corresponding structure element: </p><div class="image">
<img src="../../linear_vert.png" alt="linear_vert.png"/>
</div>
<p> and again this is represented as follows:</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment">// Specify size on vertical axis</span></div><div class="line">    <span class="keywordtype">int</span> vertical_size = vertical.rows / 30;</div><div class="line"></div><div class="line">    <span class="comment">// Create structure element for extracting vertical lines through morphology operations</span></div><div class="line">    Mat verticalStructure = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">getStructuringElement</a>(<a class="code" href="../../d4/d86/group__imgproc__filter.html#ggac2db39b56866583a95a5680313c314ada260c4cbde19a749726763c01a074c60f">MORPH_RECT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(1, vertical_size));</div><div class="line"></div><div class="line">    <span class="comment">// Apply morphology operations</span></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb">erode</a>(vertical, vertical, verticalStructure, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(-1, -1));</div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">dilate</a>(vertical, vertical, verticalStructure, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(-1, -1));</div><div class="line"></div><div class="line">    <span class="comment">// Show extracted vertical lines</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;vertical&quot;</span>, vertical);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        <span class="comment">// Specify size on vertical axis</span></div><div class="line">        <span class="keywordtype">int</span> vertical_size = vertical.rows() / 30;</div><div class="line"></div><div class="line">        <span class="comment">// Create structure element for extracting vertical lines through morphology operations</span></div><div class="line">        Mat verticalStructure = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( 1,vertical_size));</div><div class="line"></div><div class="line">        <span class="comment">// Apply morphology operations</span></div><div class="line">        Imgproc.erode(vertical, vertical, verticalStructure);</div><div class="line">        Imgproc.dilate(vertical, vertical, verticalStructure);</div><div class="line"></div><div class="line">        <span class="comment">// Show extracted vertical lines</span></div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;vertical&quot;</span>, vertical);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment"># Specify size on vertical axis</span></div><div class="line">    rows = vertical.shape[0]</div><div class="line">    verticalsize = rows // 30</div><div class="line"></div><div class="line">    <span class="comment"># Create structure element for extracting vertical lines through morphology operations</span></div><div class="line">    verticalStructure = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc">cv.getStructuringElement</a>(cv.MORPH_RECT, (1, verticalsize))</div><div class="line"></div><div class="line">    <span class="comment"># Apply morphology operations</span></div><div class="line">    vertical = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb">cv.erode</a>(vertical, verticalStructure)</div><div class="line">    vertical = <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">cv.dilate</a>(vertical, verticalStructure)</div><div class="line"></div><div class="line">    <span class="comment"># Show extracted vertical lines</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;vertical&quot;</span>, vertical)</div></div><!-- fragment --> </div> <div class="image">
<img src="../../vert.png" alt="vert.png"/>
</div>
<h4>Refine edges / Result</h4>
<p>As you can see we are almost there. However, at that point you will notice that the edges of the notes are a bit rough. For that reason we need to refine the edges in order to obtain a smoother result:</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment">// Inverse vertical image</span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga0002cf8b418479f4cb49a75442baee2f">bitwise_not</a>(vertical, vertical);</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;vertical_bit&quot;</span>, vertical);</div><div class="line"></div><div class="line">    <span class="comment">// Extract edges and smooth image according to the logic</span></div><div class="line">    <span class="comment">// 1. extract edges</span></div><div class="line">    <span class="comment">// 2. dilate(edges)</span></div><div class="line">    <span class="comment">// 3. src.copyTo(smooth)</span></div><div class="line">    <span class="comment">// 4. blur smooth img</span></div><div class="line">    <span class="comment">// 5. smooth.copyTo(src, edges)</span></div><div class="line"></div><div class="line">    <span class="comment">// Step 1</span></div><div class="line">    Mat edges;</div><div class="line">    <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3">adaptiveThreshold</a>(vertical, edges, 255, <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa42a3e6ef26247da787bf34030ed772cad0c5199ae8637a6b195062fea4789fa9">ADAPTIVE_THRESH_MEAN_C</a>, <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa9e58d2860d4afa658ef70a9b1115576a147222a96556ebc1d948b372bcd7ac59">THRESH_BINARY</a>, 3, -2);</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;edges&quot;</span>, edges);</div><div class="line"></div><div class="line">    <span class="comment">// Step 2</span></div><div class="line">    Mat kernel = Mat::ones(2, 2, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga81df635441b21f532fdace401e04f588">CV_8UC1</a>);</div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">dilate</a>(edges, edges, kernel);</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;dilate&quot;</span>, edges);</div><div class="line"></div><div class="line">    <span class="comment">// Step 3</span></div><div class="line">    Mat smooth;</div><div class="line">    vertical.copyTo(smooth);</div><div class="line"></div><div class="line">    <span class="comment">// Step 4</span></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga8c45db9afe636703801b0b2e440fce37">blur</a>(smooth, smooth, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(2, 2));</div><div class="line"></div><div class="line">    <span class="comment">// Step 5</span></div><div class="line">    smooth.copyTo(vertical, edges);</div><div class="line"></div><div class="line">    <span class="comment">// Show final result</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;smooth - final&quot;</span>, vertical);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        <span class="comment">// Inverse vertical image</span></div><div class="line">        Core.bitwise_not(vertical, vertical);</div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;vertical_bit&quot;</span> , vertical);</div><div class="line"></div><div class="line">        <span class="comment">// Extract edges and smooth image according to the logic</span></div><div class="line">        <span class="comment">// 1. extract edges</span></div><div class="line">        <span class="comment">// 2. dilate(edges)</span></div><div class="line">        <span class="comment">// 3. src.copyTo(smooth)</span></div><div class="line">        <span class="comment">// 4. blur smooth img</span></div><div class="line">        <span class="comment">// 5. smooth.copyTo(src, edges)</span></div><div class="line"></div><div class="line">        <span class="comment">// Step 1</span></div><div class="line">        Mat edges = <span class="keyword">new</span> Mat();</div><div class="line">        Imgproc.adaptiveThreshold(vertical, edges, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 3, -2);</div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;edges&quot;</span>, edges);</div><div class="line"></div><div class="line">        <span class="comment">// Step 2</span></div><div class="line">        Mat kernel = Mat.ones(2, 2, CvType.CV_8UC1);</div><div class="line">        Imgproc.dilate(edges, edges, kernel);</div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;dilate&quot;</span>, edges);</div><div class="line"></div><div class="line">        <span class="comment">// Step 3</span></div><div class="line">        Mat smooth = <span class="keyword">new</span> Mat();</div><div class="line">        vertical.copyTo(smooth);</div><div class="line"></div><div class="line">        <span class="comment">// Step 4</span></div><div class="line">        Imgproc.blur(smooth, smooth, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(2, 2));</div><div class="line"></div><div class="line">        <span class="comment">// Step 5</span></div><div class="line">        smooth.copyTo(vertical, edges);</div><div class="line"></div><div class="line">        <span class="comment">// Show final result</span></div><div class="line">        showWaitDestroy(<span class="stringliteral">&quot;smooth - final&quot;</span>, vertical);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment"># Inverse vertical image</span></div><div class="line">    vertical = <a class="code" href="../../d2/de8/group__core__array.html#ga0002cf8b418479f4cb49a75442baee2f">cv.bitwise_not</a>(vertical)</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;vertical_bit&quot;</span>, vertical)</div><div class="line"></div><div class="line">    <span class="stringliteral">&#39;&#39;&#39;</span></div><div class="line"><span class="stringliteral">    Extract edges and smooth image according to the logic</span></div><div class="line"><span class="stringliteral">    1. extract edges</span></div><div class="line"><span class="stringliteral">    2. dilate(edges)</span></div><div class="line"><span class="stringliteral">    3. src.copyTo(smooth)</span></div><div class="line"><span class="stringliteral">    4. blur smooth img</span></div><div class="line"><span class="stringliteral">    5. smooth.copyTo(src, edges)</span></div><div class="line"><span class="stringliteral">    &#39;&#39;&#39;</span></div><div class="line"></div><div class="line">    <span class="comment"># Step 1</span></div><div class="line">    edges = <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ga72b913f352e4a1b1b397736707afcde3">cv.adaptiveThreshold</a>(vertical, 255, cv.ADAPTIVE_THRESH_MEAN_C, \</div><div class="line">                                cv.THRESH_BINARY, 3, -2)</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;edges&quot;</span>, edges)</div><div class="line"></div><div class="line">    <span class="comment"># Step 2</span></div><div class="line">    kernel = np.ones((2, 2), np.uint8)</div><div class="line">    edges = <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c">cv.dilate</a>(edges, kernel)</div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;dilate&quot;</span>, edges)</div><div class="line"></div><div class="line">    <span class="comment"># Step 3</span></div><div class="line">    smooth = np.copy(vertical)</div><div class="line"></div><div class="line">    <span class="comment"># Step 4</span></div><div class="line">    smooth = <a class="code" href="../../d4/d86/group__imgproc__filter.html#ga8c45db9afe636703801b0b2e440fce37">cv.blur</a>(smooth, (2, 2))</div><div class="line"></div><div class="line">    <span class="comment"># Step 5</span></div><div class="line">    (rows, cols) = np.where(edges != 0)</div><div class="line">    vertical[rows, cols] = smooth[rows, cols]</div><div class="line"></div><div class="line">    <span class="comment"># Show final result</span></div><div class="line">    show_wait_destroy(<span class="stringliteral">&quot;smooth - final&quot;</span>, vertical)</div></div><!-- fragment --> </div> <div class="image">
<img src="../../smooth.png" alt="smooth.png"/>
</div>
 </div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:35 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
